﻿using System;
using System.Collections.Generic;
using System.Text;

namespace cuyan.lockgo
{
    
    public class LockTool
    {
        private readonly string _LockString;
        public readonly int _ThreadNo;
        private readonly Object _LockObj = new object();
        private static readonly Object _StaticLockObj = new object();

        /// <summary>
        ///     初始化<see cref=“LockGo”/>类的新实例。
        /// </summary>
        /// <param name="lockstring">锁名称</param>
        /// <param name="threadNo">线程</param>
        public LockTool(string lockstring, int threadNo)
        {
            _LockString = lockstring;
            _ThreadNo = threadNo;
        }

        /// <summary>
        ///     锁，带返回值
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="lockType">锁类型</param>
        /// <param name="assemblyName">程序集名称</param>
        /// <param name="nameSpace">命名空间</param>
        /// <param name="className">类名</param>
        /// <param name="methodName">方法名</param>
        /// <param name="classParas">构造函数参数</param>
        /// <param name="paras">调用方法参数</param>
        /// <returns></returns>
        public T Start<T>(LockType lockType, string assemblyName, string nameSpace, string className, string methodName, object[] classParas, object[] paras)
        {
            T result = default;
            //等待锁资源
            switch (lockType)
            {
                case LockType.LockThis:
                    lock (this)
                    {
                        result = ReflectionHelper.GetInvokeMethod<T>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
                case LockType.LockString:
                    lock (_LockString)
                    {
                        result = ReflectionHelper.GetInvokeMethod<T>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
                case LockType.LockObject:
                    lock (_LockObj)
                    {
                        result = ReflectionHelper.GetInvokeMethod<T>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
                case LockType.LockStaticObject:
                    lock (_StaticLockObj)
                    {
                        result = ReflectionHelper.GetInvokeMethod<T>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
            }
            //释放锁
            return result;
        }


        /// <summary>
        ///     锁，不带返回值
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="lockType">锁类型</param>
        /// <param name="assemblyName">程序集名称</param>
        /// <param name="nameSpace">命名空间</param>
        /// <param name="className">类名</param>
        /// <param name="methodName">方法名</param>
        /// <param name="classParas">构造函数参数</param>
        /// <param name="paras">调用方法参数</param>
        /// <returns></returns>
        public void Start(LockType lockType, string assemblyName, string nameSpace, string className, string methodName, object[] classParas, object[] paras)
        {
            string result;
            //等待锁资源
            switch (lockType)
            {
                case LockType.LockThis:
                    lock (this)
                    {
                        result = ReflectionHelper.GetInvokeMethod<string>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
                case LockType.LockString:
                    lock (_LockString)
                    {
                        result = ReflectionHelper.GetInvokeMethod<string>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
                case LockType.LockObject:
                    lock (_LockObj)
                    {
                        result = ReflectionHelper.GetInvokeMethod<string>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
                case LockType.LockStaticObject:
                    lock (_StaticLockObj)
                    {
                        result = ReflectionHelper.GetInvokeMethod<string>(assemblyName, nameSpace, className, methodName, classParas, paras);
                    }
                    break;
            }
            //释放锁
        }

    }

    public enum LockType
    {
        /// <summary>
        /// 当前线程锁
        /// </summary>
        LockThis = 0,
        /// <summary>
        /// 字符串锁
        /// </summary>
        LockString = 1,
        /// <summary>
        /// 对象锁
        /// </summary>
        LockObject = 2,
        /// <summary>
        /// 静态对象锁
        /// </summary>
        LockStaticObject = 3
    }
}
